package gui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import utility.Keyword;
import utility.PageInfo;

import multithreaded.ThreadedPageAnalyzer;
import multithreaded.ThreadedPageParser;
import multithreaded.ThreadedPageRetriever;

/**
 * GUI Frame for Threaded Crawler.
 * @author Daniel Anderson and Luc H. Le
 * @version TCSS422 2012
 */
@SuppressWarnings("serial")
public class ThreadedCrawlerFrame extends JFrame{

	//GUI stuff
	private List<Keyword> my_keywords;
	private JFrame my_frame;
	private JLabel my_crawled_label;
	private int my_crawled;
	private JPanel my_panel;
	private JTextArea my_text_panel;
	private boolean my_started;
	private int my_limit;
	
	//Crawler Stuff
	BlockingQueue<String> my_url_queue;
	BlockingQueue<PageInfo> my_pages;
	BlockingQueue<String> my_unfiltered_urls;
	BlockingQueue<String> my_text_queue;
	
	//RetrieverThread
	ThreadedPageRetriever my_retr;
	Thread my_retr_thread;
	//ParserThread
	ThreadedPageParser my_parser;
	Thread my_parser_thread;
	//PageAnalyzer
	ThreadedPageAnalyzer my_analyzer;
	Thread my_analyzer_thread;
	
	
	public ThreadedCrawlerFrame(List<String> keywords, String url, int num_pages) {
		super();
		my_limit = num_pages; 
		my_crawled = 0;
		my_keywords = new ArrayList<Keyword>();
		for(String key : keywords) {
			my_keywords.add(new Keyword(key));//Convert keyword string list to keyword list
		}
		my_frame = new JFrame("TCSS 422 Webcrawler: Multithreaded");
		my_crawled_label = new JLabel("Number of Pages Crawled: " + my_crawled);
		my_panel = new JPanel();
		my_text_panel = new JTextArea();
		my_started = false;
		
		//crawler queues
		my_url_queue = new LinkedBlockingQueue<String>();
		my_pages = new LinkedBlockingQueue<PageInfo>();
		my_unfiltered_urls = new LinkedBlockingQueue<String>();
		my_text_queue = new LinkedBlockingQueue<String>();
		
		my_retr = new ThreadedPageRetriever(my_pages, my_url_queue);
		my_retr_thread = new Thread(my_retr);
		my_parser = new ThreadedPageParser(my_pages, my_unfiltered_urls, my_text_queue);
		my_parser_thread = new Thread(my_parser);
		my_analyzer = new ThreadedPageAnalyzer(my_url_queue, my_unfiltered_urls, my_text_queue, my_keywords);
		my_analyzer_thread = new Thread(my_analyzer);
		
		my_url_queue.add(url);
	}
	
	public void start() {
		buildUI();
	}
	
	private void buildUI() {
		my_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		my_frame.setLayout(new BorderLayout());
		my_frame.add(my_crawled_label, BorderLayout.PAGE_START);
		my_frame.add(my_panel, BorderLayout.PAGE_END);
		
		JScrollPane text_scroll = new JScrollPane(my_text_panel);
		text_scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		text_scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		my_frame.add(text_scroll, BorderLayout.CENTER);
		
		JButton startb = new JButton("Start");
		my_panel.add(startb);
		startb.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(!my_started){
					doCrawl();
				} else {
					JOptionPane.showMessageDialog(my_frame, "Crawler has already run!",  "Crawler", JOptionPane.ERROR_MESSAGE);
				}
			}
		});
		
		my_frame.setSize(800, 600);
		my_frame.setResizable(false);
		my_frame.setVisible(true);
	}
	
	private void doCrawl() {
		long start = System.currentTimeMillis();//Start timing
		my_retr_thread.start();
		my_parser_thread.start();
		my_analyzer_thread.start();
		
		while(my_crawled < my_limit) {
			my_crawled = my_retr.getRetrievedCount();
			my_crawled_label.setText("Number of Pages Crawled: " + Integer.toString(my_crawled));
			my_crawled_label.paintImmediately(my_text_panel.getVisibleRect());
		}
		endThreads();
		long end = System.currentTimeMillis();//end timing
		long time = end-start;
		
		//Start printing stats
		my_text_panel.append("\n=================MULTITHREADED STATS==================");
		
		my_text_panel.append("\nPages retrieved: " + my_retr.getRetrievedCount());
		
		double avwords =  (double)my_analyzer.getWordCount()/my_analyzer.getPageCount();
		my_text_panel.append("\nAverage words per page: " + String.format("%.3g", avwords));
		
		double avurls = (double)my_parser.geURLCount()/my_parser.getParseCount();
		my_text_panel.append("\nAverage urls per page: " + String.format("%.3g", avurls));
		
		my_text_panel.append("\nKeyword Stats:");
		for(Keyword k : my_keywords) {
			double avhits = (double)k.getHits()/my_analyzer.getPageCount();
			my_text_panel.append("\n" + k.getWord() + "-  Average Hits per page: " + String.format("%.3g", avhits) + "  Total Hits: " + k.getHits());
		}
		
		long avparse = my_parser.getParseTime()/my_parser.getParseCount();
		my_text_panel.append("\nAverage parse time per page: " + avparse + " milliseconds");
		my_text_panel.append("\nTotal running time: " + time + " milliseconds");
	}

	private void endThreads() {
		my_retr.finish();
		my_parser.finish();
		my_analyzer.finish();
		my_retr_thread.interrupt();
		my_parser_thread.interrupt();
		my_analyzer_thread.interrupt();
	}
}



